/*
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: DTMDefaultBaseIterators.java,v 1.2.4.1 2005/09/15 08:15:00 suresh_emailid Exp $
 */
package com.sun.org.apache.xml.internal.dtm.ref;

import com.sun.org.apache.xml.internal.dtm.*;

import javax.xml.transform.Source;

import com.sun.org.apache.xml.internal.utils.XMLStringFactory;

import com.sun.org.apache.xml.internal.res.XMLErrorResources;
import com.sun.org.apache.xml.internal.res.XMLMessages;
import com.sun.org.apache.xalan.internal.xsltc.dom.NodeCounter;

/**
 * This class implements the traversers for DTMDefaultBase.
 */
public abstract class DTMDefaultBaseIterators extends DTMDefaultBaseTraversers {

    /**
     * Construct a DTMDefaultBaseTraversers object from a DOM node.
     *
     * @param mgr The DTMManager who owns this DTM.
     * @param source The object that is used to specify the construction source.
     * @param dtmIdentity The DTM identity ID for this DTM.
     * @param whiteSpaceFilter The white space filter for this DTM, which may
     *                         be null.
     * @param xstringfactory The factory to use for creating XMLStrings.
     * @param doIndexing true if the caller considers it worth it to use
     *                   indexing schemes.
     */
    public DTMDefaultBaseIterators(DTMManager mgr, Source source, int dtmIdentity, DTMWSFilter whiteSpaceFilter, XMLStringFactory xstringfactory, boolean doIndexing) {
        super(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory, doIndexing);
    }

    /**
     * Construct a DTMDefaultBaseTraversers object from a DOM node.
     *
     * @param mgr The DTMManager who owns this DTM.
     * @param source The object that is used to specify the construction source.
     * @param dtmIdentity The DTM identity ID for this DTM.
     * @param whiteSpaceFilter The white space filter for this DTM, which may
     *                         be null.
     * @param xstringfactory The factory to use for creating XMLStrings.
     * @param doIndexing true if the caller considers it worth it to use
     *                   indexing schemes.
     * @param blocksize The block size of the DTM.
     * @param usePrevsib true if we want to build the previous sibling node array.
     * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
     */
    public DTMDefaultBaseIterators(DTMManager mgr, Source source, int dtmIdentity, DTMWSFilter whiteSpaceFilter, XMLStringFactory xstringfactory, boolean doIndexing, int blocksize, boolean usePrevsib, boolean newNameTable) {
        super(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory, doIndexing, blocksize, usePrevsib, newNameTable);
    }

    /**
     * Get an iterator that can navigate over an XPath Axis, predicated by
     * the extended type ID.
     * Returns an iterator that must be initialized
     * with a start node (using iterator.setStartNode()).
     *
     * @param axis One of Axes.ANCESTORORSELF, etc.
     * @param type An extended type ID.
     *
     * @return A DTMAxisIterator, or null if the given axis isn't supported.
     */
    public DTMAxisIterator getTypedAxisIterator(int axis, int type) {

        DTMAxisIterator iterator = null;

        /* This causes an error when using patterns for elements that
           do not exist in the DOM (translet types which do not correspond
           to a DOM type are mapped to the DOM.ELEMENT type).
        */

        //        if (type == NO_TYPE) {
        //            return(EMPTYITERATOR);
        //        }
        //        else if (type == ELEMENT) {
        //            iterator = new FilterIterator(getAxisIterator(axis),
        //                                          getElementFilter());
        //        }
        //        else
        {
            switch (axis) {
                case Axis.SELF:
                    iterator = new TypedSingletonIterator(type);
                    break;
                case Axis.CHILD:
                    iterator = new TypedChildrenIterator(type);
                    break;
                case Axis.PARENT:
                    return (new ParentIterator().setNodeType(type));
                case Axis.ANCESTOR:
                    return (new TypedAncestorIterator(type));
                case Axis.ANCESTORORSELF:
                    return ((new TypedAncestorIterator(type)).includeSelf());
                case Axis.ATTRIBUTE:
                    return (new TypedAttributeIterator(type));
                case Axis.DESCENDANT:
                    iterator = new TypedDescendantIterator(type);
                    break;
                case Axis.DESCENDANTORSELF:
                    iterator = (new TypedDescendantIterator(type)).includeSelf();
                    break;
                case Axis.FOLLOWING:
                    iterator = new TypedFollowingIterator(type);
                    break;
                case Axis.PRECEDING:
                    iterator = new TypedPrecedingIterator(type);
                    break;
                case Axis.FOLLOWINGSIBLING:
                    iterator = new TypedFollowingSiblingIterator(type);
                    break;
                case Axis.PRECEDINGSIBLING:
                    iterator = new TypedPrecedingSiblingIterator(type);
                    break;
                case Axis.NAMESPACE:
                    iterator = new TypedNamespaceIterator(type);
                    break;
                case Axis.ROOT:
                    iterator = new TypedRootIterator(type);
                    break;
                default:
                    throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_TYPED_ITERATOR_AXIS_NOT_IMPLEMENTED, new Object[] { Axis.getNames(axis) }));
                    //"Error: typed iterator for axis "
                    //+ Axis.names[axis] + "not implemented");
            }
        }

        return (iterator);
    }

    /**
     * This is a shortcut to the iterators that implement the
     * XPath axes.
     * Returns a bare-bones iterator that must be initialized
     * with a start node (using iterator.setStartNode()).
     *
     * @param axis One of Axes.ANCESTORORSELF, etc.
     *
     * @return A DTMAxisIterator, or null if the given axis isn't supported.
     */
    public DTMAxisIterator getAxisIterator(final int axis) {

        DTMAxisIterator iterator = null;

        switch (axis) {
            case Axis.SELF:
                iterator = new SingletonIterator();
                break;
            case Axis.CHILD:
                iterator = new ChildrenIterator();
                break;
            case Axis.PARENT:
                return (new ParentIterator());
            case Axis.ANCESTOR:
                return (new AncestorIterator());
            case Axis.ANCESTORORSELF:
                return ((new AncestorIterator()).includeSelf());
            case Axis.ATTRIBUTE:
                return (new AttributeIterator());
            case Axis.DESCENDANT:
                iterator = new DescendantIterator();
                break;
            case Axis.DESCENDANTORSELF:
                iterator = (new DescendantIterator()).includeSelf();
                break;
            case Axis.FOLLOWING:
                iterator = new FollowingIterator();
                break;
            case Axis.PRECEDING:
                iterator = new PrecedingIterator();
                break;
            case Axis.FOLLOWINGSIBLING:
                iterator = new FollowingSiblingIterator();
                break;
            case Axis.PRECEDINGSIBLING:
                iterator = new PrecedingSiblingIterator();
                break;
            case Axis.NAMESPACE:
                iterator = new NamespaceIterator();
                break;
            case Axis.ROOT:
                iterator = new RootIterator();
                break;
            default:
                throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_AXIS_NOT_IMPLEMENTED, new Object[] { Axis.getNames(axis) }));
                //"Error: iterator for axis '" + Axis.names[axis]
                //+ "' not implemented");
        }

        return (iterator);
    }

    /**
     * Abstract superclass defining behaviors shared by all DTMDefault's
     * internal implementations of DTMAxisIterator. Subclass this (and
     * override, if necessary) to implement the specifics of an
     * individual axis iterator.
     *
     * Currently there isn't a lot here
     */
    public abstract class InternalAxisIteratorBase extends DTMAxisIteratorBase {

        // %REVIEW% We could opt to share _nodeType and setNodeType() as
        // well, and simply ignore them in iterators which don't use them.
        // But Scott's worried about the overhead involved in cloning
        // these, and wants them to have as few fields as possible. Note
        // that we can't create a TypedInternalAxisIteratorBase because
        // those are often based on the untyped versions and Java doesn't
        // support multiple inheritance. <sigh/>

        /**
         * Current iteration location. Usually this is the last location
         * returned (starting point for the next() search); for single-node
         * iterators it may instead be initialized to point to that single node.
         */
        protected int _currentNode;

        /**
         * Remembers the current node for the next call to gotoMark().
         *
         * %REVIEW% Should this save _position too?
         */
        public void setMark() {
            _markedNode = _currentNode;
        }

        /**
         * Restores the current node remembered by setMark().
         *
         * %REVEIW% Should this restore _position too?
         */
        public void gotoMark() {
            _currentNode = _markedNode;
        }

    } // end of InternalAxisIteratorBase

    /**
     * Iterator that returns all immediate children of a given node
     */
    public final class ChildrenIterator extends InternalAxisIteratorBase {

        /**
         * Setting start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * If the iterator is not restartable, this has no effect.
         * %REVIEW% Should it return/throw something in that case,
         * or set current node to END, to indicate request-not-honored?
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                _currentNode = (node == DTM.NULL) ? DTM.NULL : _firstch(makeNodeIdentity(node));

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END if no more
         * are available.
         */
        public int next() {
            if (_currentNode != NULL) {
                int node = _currentNode;
                _currentNode = _nextsib(node);
                return returnNode(makeNodeHandle(node));
            }

            return END;
        }
    } // end of ChildrenIterator

    /**
     * Iterator that returns the parent of a given node. Note that
     * this delivers only a single node; if you want all the ancestors,
     * see AncestorIterator.
     */
    public final class ParentIterator extends InternalAxisIteratorBase {

        /** The extended type ID that was requested. */
        private int _nodeType = -1;

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                _currentNode = getParent(node);

                return resetPosition();
            }

            return this;
        }

        /**
         * Set the node type of the parent that we're looking for.
         * Note that this does _not_ mean "find the nearest ancestor of
         * this type", but "yield the parent if it is of this type".
         *
         *
         * @param type extended type ID.
         *
         * @return ParentIterator configured with the type filter set.
         */
        public DTMAxisIterator setNodeType(final int type) {

            _nodeType = type;

            return this;
        }

        /**
         * Get the next node in the iteration. In this case, we return
         * only the immediate parent, _if_ it matches the requested nodeType.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            int result = _currentNode;

            if (_nodeType >= DTM.NTYPES) {
                if (_nodeType != getExpandedTypeID(_currentNode)) {
                    result = END;
                }
            } else if (_nodeType != NULL) {
                if (_nodeType != getNodeType(_currentNode)) {
                    result = END;
                }
            }

            _currentNode = END;

            return returnNode(result);
        }
    } // end of ParentIterator

    /**
     * Iterator that returns children of a given type for a given node.
     * The functionality chould be achieved by putting a filter on top
     * of a basic child iterator, but a specialised iterator is used
     * for efficiency (both speed and size of translet).
     */
    public final class TypedChildrenIterator extends InternalAxisIteratorBase {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedChildrenIterator
         *
         *
         * @param nodeType The extended type ID being requested.
         */
        public TypedChildrenIterator(int nodeType) {
            _nodeType = nodeType;
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                _currentNode = (node == DTM.NULL) ? DTM.NULL : _firstch(makeNodeIdentity(_startNode));

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            int eType;
            int node = _currentNode;

            int nodeType = _nodeType;

            if (nodeType >= DTM.NTYPES) {
                while (node != DTM.NULL && _exptype(node) != nodeType) {
                    node = _nextsib(node);
                }
            } else {
                while (node != DTM.NULL) {
                    eType = _exptype(node);
                    if (eType < DTM.NTYPES) {
                        if (eType == nodeType) {
                            break;
                        }
                    } else if (m_expandedNameTable.getType(eType) == nodeType) {
                        break;
                    }
                    node = _nextsib(node);
                }
            }

            if (node == DTM.NULL) {
                _currentNode = DTM.NULL;
                return DTM.NULL;
            } else {
                _currentNode = _nextsib(node);
                return returnNode(makeNodeHandle(node));
            }

        }
    } // end of TypedChildrenIterator

    /**
     * Iterator that returns children within a given namespace for a
     * given node. The functionality chould be achieved by putting a
     * filter on top of a basic child iterator, but a specialised
     * iterator is used for efficiency (both speed and size of translet).
     */
    public final class NamespaceChildrenIterator extends InternalAxisIteratorBase {

        /** The extended type ID being requested. */
        private final int _nsType;

        /**
         * Constructor NamespaceChildrenIterator
         *
         *
         * @param type The extended type ID being requested.
         */
        public NamespaceChildrenIterator(final int type) {
            _nsType = type;
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                _currentNode = (node == DTM.NULL) ? DTM.NULL : NOTPROCESSED;

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            if (_currentNode != DTM.NULL) {
                for (int node = (NOTPROCESSED == _currentNode) ? _firstch(makeNodeIdentity(_startNode)) : _nextsib(_currentNode); node != END; node = _nextsib(node)) {
                    if (m_expandedNameTable.getNamespaceID(_exptype(node)) == _nsType) {
                        _currentNode = node;

                        return returnNode(node);
                    }
                }
            }

            return END;
        }
    } // end of NamespaceChildrenIterator

    /**
     * Iterator that returns the namespace nodes as defined by the XPath data model
     * for a given node.
     */
    public class NamespaceIterator extends InternalAxisIteratorBase {

        /**
         * Constructor NamespaceAttributeIterator
         */
        public NamespaceIterator() {

            super();
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                _currentNode = getFirstNamespaceNode(node, true);

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            int node = _currentNode;

            if (DTM.NULL != node)
                _currentNode = getNextNamespaceNode(_startNode, node, true);

            return returnNode(node);
        }
    } // end of NamespaceIterator

    /**
     * Iterator that returns the namespace nodes as defined by the XPath data model
     * for a given node, filtered by extended type ID.
     */
    public class TypedNamespaceIterator extends NamespaceIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedNamespaceIterator
         *
         *
         * @param nodeType The extended type ID being requested.
         */
        public TypedNamespaceIterator(int nodeType) {
            super();
            _nodeType = nodeType;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            int node;

            for (node = _currentNode; node != END; node = getNextNamespaceNode(_startNode, node, true)) {
                if (getExpandedTypeID(node) == _nodeType || getNodeType(node) == _nodeType || getNamespaceType(node) == _nodeType) {
                    _currentNode = node;

                    return returnNode(node);
                }
            }

            return (_currentNode = END);
        }
    } // end of TypedNamespaceIterator

    /**
     * Iterator that returns the the root node as defined by the XPath data model
     * for a given node.
     */
    public class RootIterator extends InternalAxisIteratorBase {

        /**
         * Constructor RootIterator
         */
        public RootIterator() {

            super();
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {

            if (_isRestartable) {
                _startNode = getDocumentRoot(node);
                _currentNode = NULL;

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            if (_startNode == _currentNode)
                return NULL;

            _currentNode = _startNode;

            return returnNode(_startNode);
        }
    } // end of RootIterator

    /**
     * Iterator that returns the namespace nodes as defined by the XPath data model
     * for a given node, filtered by extended type ID.
     */
    public class TypedRootIterator extends RootIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedRootIterator
         *
         * @param nodeType The extended type ID being requested.
         */
        public TypedRootIterator(int nodeType) {
            super();
            _nodeType = nodeType;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            if (_startNode == _currentNode)
                return NULL;

            int nodeType = _nodeType;
            int node = _startNode;
            int expType = getExpandedTypeID(node);

            _currentNode = node;

            if (nodeType >= DTM.NTYPES) {
                if (nodeType == expType) {
                    return returnNode(node);
                }
            } else {
                if (expType < DTM.NTYPES) {
                    if (expType == nodeType) {
                        return returnNode(node);
                    }
                } else {
                    if (m_expandedNameTable.getType(expType) == nodeType) {
                        return returnNode(node);
                    }
                }
            }

            return END;
        }
    } // end of TypedRootIterator

    /**
     * Iterator that returns attributes within a given namespace for a node.
     */
    public final class NamespaceAttributeIterator extends InternalAxisIteratorBase {

        /** The extended type ID being requested. */
        private final int _nsType;

        /**
         * Constructor NamespaceAttributeIterator
         *
         *
         * @param nsType The extended type ID being requested.
         */
        public NamespaceAttributeIterator(int nsType) {

            super();

            _nsType = nsType;
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                _currentNode = getFirstNamespaceNode(node, false);

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            int node = _currentNode;

            if (DTM.NULL != node)
                _currentNode = getNextNamespaceNode(_startNode, node, false);

            return returnNode(node);
        }
    } // end of NamespaceAttributeIterator

    /**
     * Iterator that returns all siblings of a given node.
     */
    public class FollowingSiblingIterator extends InternalAxisIteratorBase {

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                _currentNode = makeNodeIdentity(node);

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            _currentNode = (_currentNode == DTM.NULL) ? DTM.NULL : _nextsib(_currentNode);
            return returnNode(makeNodeHandle(_currentNode));
        }
    } // end of FollowingSiblingIterator

    /**
     * Iterator that returns all following siblings of a given node.
     */
    public final class TypedFollowingSiblingIterator extends FollowingSiblingIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedFollowingSiblingIterator
         *
         *
         * @param type The extended type ID being requested.
         */
        public TypedFollowingSiblingIterator(int type) {
            _nodeType = type;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            if (_currentNode == DTM.NULL) {
                return DTM.NULL;
            }

            int node = _currentNode;
            int eType;
            int nodeType = _nodeType;

            if (nodeType >= DTM.NTYPES) {
                do {
                    node = _nextsib(node);
                } while (node != DTM.NULL && _exptype(node) != nodeType);
            } else {
                while ((node = _nextsib(node)) != DTM.NULL) {
                    eType = _exptype(node);
                    if (eType < DTM.NTYPES) {
                        if (eType == nodeType) {
                            break;
                        }
                    } else if (m_expandedNameTable.getType(eType) == nodeType) {
                        break;
                    }
                }
            }

            _currentNode = node;

            return (_currentNode == DTM.NULL) ? DTM.NULL : returnNode(makeNodeHandle(_currentNode));
        }
    } // end of TypedFollowingSiblingIterator

    /**
     * Iterator that returns attribute nodes (of what nodes?)
     */
    public final class AttributeIterator extends InternalAxisIteratorBase {

        // assumes caller will pass element nodes

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                _currentNode = getFirstAttributeIdentity(makeNodeIdentity(node));

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            final int node = _currentNode;

            if (node != NULL) {
                _currentNode = getNextAttributeIdentity(node);
                return returnNode(makeNodeHandle(node));
            }

            return NULL;
        }
    } // end of AttributeIterator

    /**
     * Iterator that returns attribute nodes of a given type
     */
    public final class TypedAttributeIterator extends InternalAxisIteratorBase {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedAttributeIterator
         *
         *
         * @param nodeType The extended type ID that is requested.
         */
        public TypedAttributeIterator(int nodeType) {
            _nodeType = nodeType;
        }

        // assumes caller will pass element nodes

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            if (_isRestartable) {
                _startNode = node;

                _currentNode = getTypedAttribute(node, _nodeType);

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            final int node = _currentNode;

            // singleton iterator, since there can only be one attribute of
            // a given type.
            _currentNode = NULL;

            return returnNode(node);
        }
    } // end of TypedAttributeIterator

    /**
     * Iterator that returns preceding siblings of a given node
     */
    public class PrecedingSiblingIterator extends InternalAxisIteratorBase {

        /**
         * The node identity of _startNode for this iterator
         */
        protected int _startNodeID;

        /**
         * True if this iterator has a reversed axis.
         *
         * @return true.
         */
        public boolean isReverse() {
            return true;
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;
                node = _startNodeID = makeNodeIdentity(node);

                if (node == NULL) {
                    _currentNode = node;
                    return resetPosition();
                }

                int type = m_expandedNameTable.getType(_exptype(node));
                if (ExpandedNameTable.ATTRIBUTE == type || ExpandedNameTable.NAMESPACE == type) {
                    _currentNode = node;
                } else {
                    // Be careful to handle the Document node properly
                    _currentNode = _parent(node);
                    if (NULL != _currentNode)
                        _currentNode = _firstch(_currentNode);
                    else
                        _currentNode = node;
                }

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            if (_currentNode == _startNodeID || _currentNode == DTM.NULL) {
                return NULL;
            } else {
                final int node = _currentNode;
                _currentNode = _nextsib(node);

                return returnNode(makeNodeHandle(node));
            }
        }
    } // end of PrecedingSiblingIterator

    /**
     * Iterator that returns preceding siblings of a given type for
     * a given node
     */
    public final class TypedPrecedingSiblingIterator extends PrecedingSiblingIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedPrecedingSiblingIterator
         *
         *
         * @param type The extended type ID being requested.
         */
        public TypedPrecedingSiblingIterator(int type) {
            _nodeType = type;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            int node = _currentNode;
            int expType;

            int nodeType = _nodeType;
            int startID = _startNodeID;

            if (nodeType >= DTM.NTYPES) {
                while (node != NULL && node != startID && _exptype(node) != nodeType) {
                    node = _nextsib(node);
                }
            } else {
                while (node != NULL && node != startID) {
                    expType = _exptype(node);
                    if (expType < DTM.NTYPES) {
                        if (expType == nodeType) {
                            break;
                        }
                    } else {
                        if (m_expandedNameTable.getType(expType) == nodeType) {
                            break;
                        }
                    }
                    node = _nextsib(node);
                }
            }

            if (node == DTM.NULL || node == _startNodeID) {
                _currentNode = NULL;
                return NULL;
            } else {
                _currentNode = _nextsib(node);
                return returnNode(makeNodeHandle(node));
            }
        }
    } // end of TypedPrecedingSiblingIterator

    /**
     * Iterator that returns preceding nodes of a given node.
     * This includes the node set {root+1, start-1}, but excludes
     * all ancestors, attributes, and namespace nodes.
     */
    public class PrecedingIterator extends InternalAxisIteratorBase {

        /** The max ancestors, but it can grow... */
        private final int _maxAncestors = 8;

        /**
         * The stack of start node + ancestors up to the root of the tree,
         *  which we must avoid.
         */
        protected int[] _stack = new int[_maxAncestors];

        /** (not sure yet... -sb) */
        protected int _sp, _oldsp;

        protected int _markedsp, _markedNode, _markedDescendant;

        /* _currentNode precedes candidates.  This is the identity, not the handle! */

        /**
         * True if this iterator has a reversed axis.
         *
         * @return true since this iterator is a reversed axis.
         */
        public boolean isReverse() {
            return true;
        }

        /**
         * Returns a deep copy of this iterator.   The cloned iterator is not reset.
         *
         * @return a deep copy of this iterator.
         */
        public DTMAxisIterator cloneIterator() {
            _isRestartable = false;

            try {
                final PrecedingIterator clone = (PrecedingIterator) super.clone();
                final int[] stackCopy = new int[_stack.length];
                System.arraycopy(_stack, 0, stackCopy, 0, _stack.length);

                clone._stack = stackCopy;

                // return clone.reset();
                return clone;
            } catch (CloneNotSupportedException e) {
                throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
            }
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                node = makeNodeIdentity(node);

                // iterator is not a clone
                int parent, index;

                if (_type(node) == DTM.ATTRIBUTE_NODE)
                    node = _parent(node);

                _startNode = node;
                _stack[index = 0] = node;

                parent = node;
                while ((parent = _parent(parent)) != NULL) {
                    if (++index == _stack.length) {
                        final int[] stack = new int[index + 4];
                        System.arraycopy(_stack, 0, stack, 0, index);
                        _stack = stack;
                    }
                    _stack[index] = parent;
                }
                if (index > 0)
                    --index; // Pop actual root node (if not start) back off the stack

                _currentNode = _stack[index]; // Last parent before root node

                _oldsp = _sp = index;

                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            // Bugzilla 8324: We were forgetting to skip Attrs and NS nodes.
            // Also recoded the loop controls for clarity and to flatten out
            // the tail-recursion.
            for (++_currentNode; _sp >= 0; ++_currentNode) {
                if (_currentNode < _stack[_sp]) {
                    if (_type(_currentNode) != ATTRIBUTE_NODE && _type(_currentNode) != NAMESPACE_NODE)
                        return returnNode(makeNodeHandle(_currentNode));
                } else
                    --_sp;
            }
            return NULL;
        }

        // redefine DTMAxisIteratorBase's reset

        /**
         * Resets the iterator to the last start node.
         *
         * @return A DTMAxisIterator, which may or may not be the same as this
         *         iterator.
         */
        public DTMAxisIterator reset() {

            _sp = _oldsp;

            return resetPosition();
        }

        public void setMark() {
            _markedsp = _sp;
            _markedNode = _currentNode;
            _markedDescendant = _stack[0];
        }

        public void gotoMark() {
            _sp = _markedsp;
            _currentNode = _markedNode;
        }
    } // end of PrecedingIterator

    /**
     * Iterator that returns preceding nodes of agiven type for a
     * given node. This includes the node set {root+1, start-1}, but
     * excludes all ancestors.
     */
    public final class TypedPrecedingIterator extends PrecedingIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedPrecedingIterator
         *
         *
         * @param type The extended type ID being requested.
         */
        public TypedPrecedingIterator(int type) {
            _nodeType = type;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            int node = _currentNode;
            int nodeType = _nodeType;

            if (nodeType >= DTM.NTYPES) {
                while (true) {
                    node = node + 1;

                    if (_sp < 0) {
                        node = NULL;
                        break;
                    } else if (node >= _stack[_sp]) {
                        if (--_sp < 0) {
                            node = NULL;
                            break;
                        }
                    } else if (_exptype(node) == nodeType) {
                        break;
                    }
                }
            } else {
                int expType;

                while (true) {
                    node = node + 1;

                    if (_sp < 0) {
                        node = NULL;
                        break;
                    } else if (node >= _stack[_sp]) {
                        if (--_sp < 0) {
                            node = NULL;
                            break;
                        }
                    } else {
                        expType = _exptype(node);
                        if (expType < DTM.NTYPES) {
                            if (expType == nodeType) {
                                break;
                            }
                        } else {
                            if (m_expandedNameTable.getType(expType) == nodeType) {
                                break;
                            }
                        }
                    }
                }
            }

            _currentNode = node;

            return (node == NULL) ? NULL : returnNode(makeNodeHandle(node));
        }
    } // end of TypedPrecedingIterator

    /**
     * Iterator that returns following nodes of for a given node.
     */
    public class FollowingIterator extends InternalAxisIteratorBase {
        DTMAxisTraverser m_traverser; // easier for now

        public FollowingIterator() {
            m_traverser = getAxisTraverser(Axis.FOLLOWING);
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                _startNode = node;

                // ?? -sb
                // find rightmost descendant (or self)
                // int current;
                // while ((node = getLastChild(current = node)) != NULL){}
                // _currentNode = current;
                _currentNode = m_traverser.first(node);

                // _currentNode precedes possible following(node) nodes
                return resetPosition();
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            int node = _currentNode;

            _currentNode = m_traverser.next(_startNode, _currentNode);

            return returnNode(node);
        }
    } // end of FollowingIterator

    /**
     * Iterator that returns following nodes of a given type for a given node.
     */
    public final class TypedFollowingIterator extends FollowingIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedFollowingIterator
         *
         *
         * @param type The extended type ID being requested.
         */
        public TypedFollowingIterator(int type) {
            _nodeType = type;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            int node;

            do {
                node = _currentNode;

                _currentNode = m_traverser.next(_startNode, _currentNode);

            } while (node != DTM.NULL && (getExpandedTypeID(node) != _nodeType && getNodeType(node) != _nodeType));

            return (node == DTM.NULL ? DTM.NULL : returnNode(node));
        }
    } // end of TypedFollowingIterator

    /**
     * Iterator that returns the ancestors of a given node in document
     * order.  (NOTE!  This was changed from the XSLTC code!)
     */
    public class AncestorIterator extends InternalAxisIteratorBase {
        com.sun.org.apache.xml.internal.utils.NodeVector m_ancestors = new com.sun.org.apache.xml.internal.utils.NodeVector();

        int m_ancestorsPos;

        int m_markedPos;

        /** The real start node for this axes, since _startNode will be adjusted. */
        int m_realStartNode;

        /**
         * Get start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @return The root node of the iteration.
         */
        public int getStartNode() {
            return m_realStartNode;
        }

        /**
         * True if this iterator has a reversed axis.
         *
         * @return true since this iterator is a reversed axis.
         */
        public final boolean isReverse() {
            return true;
        }

        /**
         * Returns a deep copy of this iterator.  The cloned iterator is not reset.
         *
         * @return a deep copy of this iterator.
         */
        public DTMAxisIterator cloneIterator() {
            _isRestartable = false; // must set to false for any clone

            try {
                final AncestorIterator clone = (AncestorIterator) super.clone();

                clone._startNode = _startNode;

                // return clone.reset();
                return clone;
            } catch (CloneNotSupportedException e) {
                throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
            }
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            m_realStartNode = node;

            if (_isRestartable) {
                int nodeID = makeNodeIdentity(node);

                if (!_includeSelf && node != DTM.NULL) {
                    nodeID = _parent(nodeID);
                    node = makeNodeHandle(nodeID);
                }

                _startNode = node;

                while (nodeID != END) {
                    m_ancestors.addElement(node);
                    nodeID = _parent(nodeID);
                    node = makeNodeHandle(nodeID);
                }
                m_ancestorsPos = m_ancestors.size() - 1;

                _currentNode = (m_ancestorsPos >= 0) ? m_ancestors.elementAt(m_ancestorsPos) : DTM.NULL;

                return resetPosition();
            }

            return this;
        }

        /**
         * Resets the iterator to the last start node.
         *
         * @return A DTMAxisIterator, which may or may not be the same as this
         *         iterator.
         */
        public DTMAxisIterator reset() {

            m_ancestorsPos = m_ancestors.size() - 1;

            _currentNode = (m_ancestorsPos >= 0) ? m_ancestors.elementAt(m_ancestorsPos) : DTM.NULL;

            return resetPosition();
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            int next = _currentNode;

            int pos = --m_ancestorsPos;

            _currentNode = (pos >= 0) ? m_ancestors.elementAt(m_ancestorsPos) : DTM.NULL;

            return returnNode(next);
        }

        public void setMark() {
            m_markedPos = m_ancestorsPos;
        }

        public void gotoMark() {
            m_ancestorsPos = m_markedPos;
            _currentNode = m_ancestorsPos >= 0 ? m_ancestors.elementAt(m_ancestorsPos) : DTM.NULL;
        }
    } // end of AncestorIterator

    /**
     * Typed iterator that returns the ancestors of a given node.
     */
    public final class TypedAncestorIterator extends AncestorIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedAncestorIterator
         *
         *
         * @param type The extended type ID being requested.
         */
        public TypedAncestorIterator(int type) {
            _nodeType = type;
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            m_realStartNode = node;

            if (_isRestartable) {
                int nodeID = makeNodeIdentity(node);
                int nodeType = _nodeType;

                if (!_includeSelf && node != DTM.NULL) {
                    nodeID = _parent(nodeID);
                }

                _startNode = node;

                if (nodeType >= DTM.NTYPES) {
                    while (nodeID != END) {
                        int eType = _exptype(nodeID);

                        if (eType == nodeType) {
                            m_ancestors.addElement(makeNodeHandle(nodeID));
                        }
                        nodeID = _parent(nodeID);
                    }
                } else {
                    while (nodeID != END) {
                        int eType = _exptype(nodeID);

                        if ((eType >= DTM.NTYPES && m_expandedNameTable.getType(eType) == nodeType) || (eType < DTM.NTYPES && eType == nodeType)) {
                            m_ancestors.addElement(makeNodeHandle(nodeID));
                        }
                        nodeID = _parent(nodeID);
                    }
                }
                m_ancestorsPos = m_ancestors.size() - 1;

                _currentNode = (m_ancestorsPos >= 0) ? m_ancestors.elementAt(m_ancestorsPos) : DTM.NULL;

                return resetPosition();
            }

            return this;
        }
    } // end of TypedAncestorIterator

    /**
     * Iterator that returns the descendants of a given node.
     */
    public class DescendantIterator extends InternalAxisIteratorBase {

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isRestartable) {
                node = makeNodeIdentity(node);
                _startNode = node;

                if (_includeSelf)
                    node--;

                _currentNode = node;

                return resetPosition();
            }

            return this;
        }

        /**
         * Tell if this node identity is a descendant.  Assumes that
         * the node info for the element has already been obtained.
         *
         * This one-sided test works only if the parent has been
         * previously tested and is known to be a descendent. It fails if
         * the parent is the _startNode's next sibling, or indeed any node
         * that follows _startNode in document order.  That may suffice
         * for this iterator, but it's not really an isDescendent() test.
         * %REVIEW% rename?
         *
         * @param identity The index number of the node in question.
         * @return true if the index is a descendant of _startNode.
         */
        protected boolean isDescendant(int identity) {
            return (_parent(identity) >= _startNode) || (_startNode == identity);
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            if (_startNode == NULL) {
                return NULL;
            }

            if (_includeSelf && (_currentNode + 1) == _startNode)
                return returnNode(makeNodeHandle(++_currentNode)); // | m_dtmIdent);

            int node = _currentNode;
            int type;

            do {
                node++;
                type = _type(node);

                if (NULL == type || !isDescendant(node)) {
                    _currentNode = NULL;
                    return END;
                }
            } while (ATTRIBUTE_NODE == type || TEXT_NODE == type || NAMESPACE_NODE == type);

            _currentNode = node;
            return returnNode(makeNodeHandle(node)); // make handle.
        }

        /**
         * Reset.
         *
         */
        public DTMAxisIterator reset() {

            final boolean temp = _isRestartable;

            _isRestartable = true;

            setStartNode(makeNodeHandle(_startNode));

            _isRestartable = temp;

            return this;
        }

    } // end of DescendantIterator

    /**
     * Typed iterator that returns the descendants of a given node.
     */
    public final class TypedDescendantIterator extends DescendantIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedDescendantIterator
         *
         *
         * @param nodeType Extended type ID being requested.
         */
        public TypedDescendantIterator(int nodeType) {
            _nodeType = nodeType;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {
            int node;
            int type;

            if (_startNode == NULL) {
                return NULL;
            }

            node = _currentNode;

            do {
                node++;
                type = _type(node);

                if (NULL == type || !isDescendant(node)) {
                    _currentNode = NULL;
                    return END;
                }
            } while (type != _nodeType && _exptype(node) != _nodeType);

            _currentNode = node;
            return returnNode(makeNodeHandle(node));
        }
    } // end of TypedDescendantIterator

    /**
     * Iterator that returns the descendants of a given node.
     * I'm not exactly clear about this one... -sb
     */
    public class NthDescendantIterator extends DescendantIterator {

        /** The current nth position. */
        int _pos;

        /**
         * Constructor NthDescendantIterator
         *
         *
         * @param pos The nth position being requested.
         */
        public NthDescendantIterator(int pos) {
            _pos = pos;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            // I'm not exactly clear yet what this is doing... -sb
            int node;

            while ((node = super.next()) != END) {
                node = makeNodeIdentity(node);

                int parent = _parent(node);
                int child = _firstch(parent);
                int pos = 0;

                do {
                    int type = _type(child);

                    if (ELEMENT_NODE == type)
                        pos++;
                } while ((pos < _pos) && (child = _nextsib(child)) != END);

                if (node == child)
                    return node;
            }

            return (END);
        }
    } // end of NthDescendantIterator

    /**
     * Class SingletonIterator.
     */
    public class SingletonIterator extends InternalAxisIteratorBase {

        /** (not sure yet what this is.  -sb)  (sc & sb remove final to compile in JDK 1.1.8) */
        private boolean _isConstant;

        /**
         * Constructor SingletonIterator
         *
         */
        public SingletonIterator() {
            this(Integer.MIN_VALUE, false);
        }

        /**
         * Constructor SingletonIterator
         *
         *
         * @param node The node handle to return.
         */
        public SingletonIterator(int node) {
            this(node, false);
        }

        /**
         * Constructor SingletonIterator
         *
         *
         * @param node the node handle to return.
         * @param constant (Not sure what this is yet.  -sb)
         */
        public SingletonIterator(int node, boolean constant) {
            _currentNode = _startNode = node;
            _isConstant = constant;
        }

        /**
         * Set start to END should 'close' the iterator,
         * i.e. subsequent call to next() should return END.
         *
         * @param node Sets the root of the iteration.
         *
         * @return A DTMAxisIterator set to the start of the iteration.
         */
        public DTMAxisIterator setStartNode(int node) {
            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
            if (node == DTMDefaultBase.ROOTNODE)
                node = getDocument();
            if (_isConstant) {
                _currentNode = _startNode;

                return resetPosition();
            } else if (_isRestartable) {
                _currentNode = _startNode = node;

                return resetPosition();
            }

            return this;
        }

        /**
         * Resets the iterator to the last start node.
         *
         * @return A DTMAxisIterator, which may or may not be the same as this
         *         iterator.
         */
        public DTMAxisIterator reset() {

            if (_isConstant) {
                _currentNode = _startNode;

                return resetPosition();
            } else {
                final boolean temp = _isRestartable;

                _isRestartable = true;

                setStartNode(_startNode);

                _isRestartable = temp;
            }

            return this;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            final int result = _currentNode;

            _currentNode = END;

            return returnNode(result);
        }
    } // end of SingletonIterator

    /**
     * Iterator that returns a given node only if it is of a given type.
     */
    public final class TypedSingletonIterator extends SingletonIterator {

        /** The extended type ID that was requested. */
        private final int _nodeType;

        /**
         * Constructor TypedSingletonIterator
         *
         *
         * @param nodeType The extended type ID being requested.
         */
        public TypedSingletonIterator(int nodeType) {
            _nodeType = nodeType;
        }

        /**
         * Get the next node in the iteration.
         *
         * @return The next node handle in the iteration, or END.
         */
        public int next() {

            //final int result = super.next();
            final int result = _currentNode;
            int nodeType = _nodeType;

            _currentNode = END;

            if (nodeType >= DTM.NTYPES) {
                if (getExpandedTypeID(result) == nodeType) {
                    return returnNode(result);
                }
            } else {
                if (getNodeType(result) == nodeType) {
                    return returnNode(result);
                }
            }

            return NULL;
        }
    } // end of TypedSingletonIterator
}
